#ifndef __FAT32_H_
#define __FAT32_H_

#include "types.h"

#define FAT_ENTRY_SIZE 4
#define FAT_ENTRY_NUM 8192
#define FAT_FILE_END 0x0FFFFFFF
#define SHORT_FILENAME_SIZE 8
#define SHORT_EXTENSION_SIZE 3

#define ATTR_READ_ONLY  0x01
#define ATTR_HIDDEN 	0x02
#define ATTR_SYSTEM 	0x04
#define ATTR_VOLUME_ID 	0x08
#define ATTR_DIRECTORY	0x10
#define ATTR_ARCHIVE  	0x20
#define ATTR_LONG_NAME (ATTR_READ_ONLY |ATTR_HIDDEN |ATTR_SYSTEM |ATTR_VOLUME_ID)

/* @note: may not be real type, need CAST before using
 * Volumn Type indicates the read type
 */
typedef struct {
/*Offset	Size	Type	*/
/* 0		3				*/	char 	BS_jmpBoot[3];
/* 3 		8				*/	char 	BS_OEMName[8];
/* 11		2		uint16	*/	char 	BPB_BytsPerSec[2];
/* 13 		1				*/	uint8 	BPB_SecPerClus;
/* 14		2				*/	uint16 	BPB_RsvdSecCnt;
/* 16		1				*/	uint8 	BPB_NumFATs;
/* 17		2		uint16	*/	char	BPB_RootEntCnt[2];	// must be 0 for FAT32
/* 19		2		uint16	*/	char	BPB_TotSec16[2];	// must be 0 for FAT32
/* 21		1				*/	char	BPB_Media;
/* 22		2				*/	uint16	BPB_FATSz16; 		// must be 0 for FAT32
/* 24		2				*/	uint16	BPB_SecPerTrk;
/* 26		2				*/	uint16	BPB_NumHeads;
/* 28		4				*/	uint32	BPB_HiddSec;
/* 32		4				*/	uint32	BPB_TotSec32;
/* 36		4				*/	uint32	BPB_FATSz32;
/* 40		2				*/	uint16	BPB_ExtFlags;
/* 42		2				*/	uint16	BPB_FSVer;
/* 44		4				*/	uint32	BPB_RootClus;
/* 48		2				*/	uint16	BPB_FSInfo;
/* 50		2				*/	uint16	BPB_BkBootSec;
/* 52		12				*/	char	BPB_Reserved[12];
/* 64		1		uint8	*/	char	BS_DrvNum;
/* 65		1				*/	char	BS_Reserved1;
/* 66		1		uint8	*/	char	BS_BootSig;
/* 67		4		uint32	*/	char	BS_VolID[4];
/* 71		11				*/	char	BS_VolLab[11];
/* 82		8				*/	char	BS_FilSysType[8];
} FAT32_BPB __attribute((aligned (1)));

/* @brief: short directory entry
 */
typedef struct {
/*Offset	Size*/
/* 0		11	*/	char 	DIR_Name[11];
/* 11 		1	*/	uint8 	DIR_Attr;
/* 12		1	*/	uint8 	DIR_NTRes;
/* 13 		1	*/	uint8 	DIR_CrtTimeTenth;
/* 14		2	*/	uint16 	DIR_CrtTime;
/* 16 		2	*/	uint16 	DIR_CrtDate;
/* 18		2	*/	uint16 	DIR_LstAccDate;
/* 20 		2	*/	uint16 	DIR_FstClusHI;
/* 22		2	*/	uint16 	DIR_WrtTime;
/* 24 		2	*/	uint16 	DIR_WrtDate;
/* 26		2	*/	uint16 	DIR_FstClusLO;
/* 28 		4	*/	uint32 	DIR_FileSize;
} short_dentry;

/* @brief: long directory entry
 */
typedef struct {
/*Offset	Size*/
/* 0		1	*/	uint8 	LDIR_Ord;
/* 1 		10	*/	uint16 	LDIR_Name1[5];
/* 11		1	*/	uint8 	DIR_NTRes;
/* 12 		1	*/	uint8 	DIR_CrtTimeTenth;
/* 13		1	*/	uint16 	DIR_CrtTime;
/* 14 		12	*/	uint16 	DIR_CrtDate[6];
/* 26		2	*/	uint16 	DIR_LstAccDate;
/* 28 		4	*/	uint16 	DIR_FstClusHI[2];
} long_dentry;

void fat32_init();
int fat32_openat(int fd, char *filename, int flags, int mode);
int fat32_read(int fd, void *buf, uint32 size);
#endif
